package com.woniu113.junk.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu113.junk.commons.util.RedisUtil;
import com.woniu113.junk.user.Param.AccountLogParam;
import com.woniu113.junk.user.Param.adminInfo.*;
import com.woniu113.junk.user.client.SiteClient;
import com.woniu113.junk.user.dto.AdminInfoDto;
import com.woniu113.junk.user.dto.FindSuitableRiderDTO;
import com.woniu113.junk.user.dto.adminInfo.AllAdminInfoDto;
import com.woniu113.junk.user.dto.adminInfo.FindAdminDTO;
import com.woniu113.junk.user.dto.adminInfo.findByStationIdDTO;
import com.woniu113.junk.user.dto.userinfo.FindUserInfoDTO;
import com.woniu113.junk.user.exception.UserException;
import com.woniu113.junk.user.mapper.AdminRoleMapper;
import com.woniu113.junk.user.mapper.LogMapper;
import com.woniu113.junk.user.model.AdminInfo;
import com.woniu113.junk.user.mapper.AdminInfoMapper;
import com.woniu113.junk.user.model.Log;
import com.woniu113.junk.user.model.UserInfo;
import com.woniu113.junk.user.service.AdminInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu113.junk.user.util.MD5Util;
import com.woniu113.junk.user.util.RedisKeyUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 蜡笔没了小新
 * @since 2024年10月19日
 */
@Service
public class AdminInfoServiceImpl extends ServiceImpl<AdminInfoMapper, AdminInfo> implements AdminInfoService {
    @Resource
    AdminInfoMapper adminInfoMapper;
    @Resource
    private LogMapper logMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private SiteClient siteClient;
    @Resource
    private AdminRoleMapper adminRoleMapper;

    @Override
    public AdminInfo adminLog(AccountLogParam param) throws Exception {
        //1.通过管理员姓名查询管理员信息,判断账户存在性和账户状态是否异常
        QueryWrapper<AdminInfo> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("admin_name",param.getUserName());
        List<AdminInfo> adminInfos = adminInfoMapper.selectList(queryWrapper);
        if (adminInfos.isEmpty()){//没查到
            throw new UserException("账号不存在",2001);
        }
        AdminInfo adminInfo = adminInfos.get(0);//取出第一个数据
        if (adminInfo.getAdminState()!= 0){//状态不为0正常
            throw new UserException("账号状态异常",2002);
        }
        //2.判断管理员密码是否正确
        if (!adminInfo.getPassword().equals(MD5Util.md5(param.getPassword(),param.getUserName()))){//密码不同
            throw new UserException("密码错误",2003);
        }
        //写入登录日志
        Log log = new Log();
        log.setAccountId(adminInfo.getAdminId());
        log.setLogTime(LocalDateTime.now());
        log.setUserType(adminInfo.getRoleId());
        log.setLoginHost(InetAddress.getLocalHost().getHostAddress());
        log.setControls("登录");
        logMapper.insert(log);
        //以上条件均通过,返回
        return adminInfo;
    }

    @Override
    /*禁用账户*/
    public void disableAccount(Integer adminId) {
        /*查询账户*/
        AdminInfo adminInfo = adminInfoMapper.selectById(adminId);
        if (adminInfo==null)throw new UserException("管理员不存在",2001);
        if (adminInfo.getAdminState()!=0)throw new UserException("管理员状态异常",2002);
        /*修改账户状态*/
        adminInfo.setAdminState(1);
        adminInfoMapper.updateById(adminInfo);
    }

    @Override
    /*启用账户*/
    public void enableAccount(Integer adminId) {
        /*查询账户*/
        AdminInfo adminInfo = adminInfoMapper.selectById(adminId);
        if (adminInfo==null)throw new UserException("管理员不存在",2001);
        if (adminInfo.getAdminState()!=1)throw new UserException("管理员状态异常",2002);
        /*修改账户状态*/
        adminInfo.setAdminState(0);
        adminInfoMapper.updateById(adminInfo);
    }

    @Override
    /*删除账户*/
    public void deleteAccount(Integer adminId) {
        /*查询账户*/
        AdminInfo adminInfo = adminInfoMapper.selectById(adminId);
        if (adminInfo==null)throw new UserException("管理员不存在",2001);
        if (adminInfo.getAdminState()==2)throw new UserException("管理员状态异常",2002);
        /*修改账户状态*/
        adminInfo.setAdminState(2);
        adminInfoMapper.updateById(adminInfo);
    }

    @Override
    public void addAdmin(AddAdminParam param) throws Exception {
        //1.判断账户是否已存在
        AdminInfo adminInfo1 = BeanUtil.toBean(param, AdminInfo.class);
        QueryWrapper<AdminInfo> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("admin_name",param.getAdminName()).ne("admin_state",2);
        AdminInfo adminInfo2 = adminInfoMapper.selectOne(queryWrapper);
        if (adminInfo2!=null){
            throw new UserException("该用户已存在",2001);
        }
        //2.判断手机号是否已存在
        QueryWrapper<AdminInfo> queryWrapper1 =new QueryWrapper<>();
        queryWrapper1.eq("admin_phone",param.getAdminPhone()).ne("admin_state",2);
        AdminInfo adminInfo = adminInfoMapper.selectOne(queryWrapper1);
        if (adminInfo!=null){
            throw new UserException("该手机号已存在",2001);
        }
        adminInfo1.setPassword(MD5Util.md5(param.getPassword(),param.getAdminName()));
        adminInfo1.setAdminState(0);
        adminInfoMapper.insert(adminInfo1);
    }

    @Override
    public void userCheckOldPassword(AdminPasswordParam param) throws Exception {
        //1.通过用户id查询用户信息
        AdminInfo adminInfo = adminInfoMapper.selectById(param.getUserId());
        //2.判断用户是否存在
        if (adminInfo==null)throw new UserException("用户不存在",2001);
        if (adminInfo.getAdminState()!=0)throw new UserException("用户状态异常",2002);
        //3.判断密码是否为空
        if (param.getPassword()==null)throw new UserException("密码为空",2002);
        String md5 = MD5Util.md5(param.getPassword(), adminInfo.getAdminName());
        //4.判断密码是否正确
        if (!md5.equals(adminInfo.getPassword()))throw new UserException("密码错误",2003);
    }

    @Override
    public void userUpdatePassword(AdminPasswordParam param) throws Exception {
        //1.通过用户id查询用户信息
        AdminInfo adminInfo = adminInfoMapper.selectById(param.getUserId());
        //2.判断用户是否存在
        if (adminInfo==null)throw new UserException("用户不存在",2001);
        if (adminInfo.getAdminState()!=0)throw new UserException("用户状态异常",2002);
        //3.判断密码是否为空
        if (param.getPassword()==null)throw new UserException("密码为空",2002);
        //4.修改密码
        adminInfo.setPassword(MD5Util.md5(param.getPassword(),adminInfo.getAdminName()));
        adminInfoMapper.updateById(adminInfo);
    }

    @Override
    public void assignRoles(AdminAssignRolesParam param) {
        AdminInfo adminInfo = adminInfoMapper.selectById(param.getAdminId());
        if (adminInfo==null)throw new UserException("用户不存在",2001);
        if (adminInfo.getAdminState()!=0)throw new UserException("用户状态异常",2002);
        adminInfo.setRoleId(param.getRoleId());
    }

//    @Override
//    /*分页查询管理员信息*/
//    public Page<AdminInfoDto> selectAdminInfo(SelectAdminInfoParam param) {
//        //1.分页查询
//        Page<AdminInfoDto> page = new Page<>(param.getPageNum(), param.getPageSize());
//        //2.查询
//        List<AdminInfoDto> adminInfoDto = adminInfoMapper.selectAdminInfo(param.getRealName(),param.getAdminState(),param.getRoleId(),page);
//        page.setRecords(adminInfoDto);
//        page.setTotal(adminInfoDto.size());
//        return page;
//    }

    @Override
    /*分页查询管理员信息*/
    public AllAdminInfoDto selectAdminInfo(SelectAdminInfoParam param, Integer offset) {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        if (param.getRealName()!=null && !param.getRealName().equals("")){
            queryWrapper.eq("admin_name",param.getRealName());
        }
        if (param.getRoleId()!=null){
            queryWrapper.eq("role_id",param.getRoleId());
        }
        if (param.getAdminState()!=null){
            queryWrapper.eq("admin_state",param.getAdminState());
        }
        int size =Math.toIntExact(adminInfoMapper.selectCount(queryWrapper));
        queryWrapper.last("LIMIT " + offset + ", " + param.getPageSize());
        ArrayList<AdminInfoDto> adminInfoDtos = new ArrayList<>();
        List<AdminInfo> infos = adminInfoMapper.selectList(queryWrapper);
        for (AdminInfo info : infos) {
            String roleName = adminRoleMapper.selectRoleNameById(info.getRoleId());
            AdminInfoDto adminInfoDto = BeanUtil.toBean(info, AdminInfoDto.class);
            adminInfoDto.setRoleType(roleName);
            adminInfoDtos.add(adminInfoDto);
        }
        AllAdminInfoDto dto = new AllAdminInfoDto();
        dto.setList(adminInfoDtos);
        dto.setTotal(size);
        return dto;
    }

    @Override
    /*修改所属站点*/
    public void editStationId(EditStationIdParam param) {
        //1.查询
        AdminInfo adminInfo = adminInfoMapper.selectById(param.getAdminId());
        //2.判断
        if (adminInfo==null)throw new UserException("用户不存在",2001);
        if (adminInfo.getAdminState()!=0)throw new UserException("用户状态异常",2002);
        //3.修改
        adminInfo.setStationId(param.getStationId());
        adminInfoMapper.updateById(adminInfo);
    }

    @Override
    public AdminInfo selectAdminById2(Integer adminId) {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("admin_id",adminId).eq("admin_state",0).eq("station_id",0);
        return adminInfoMapper.selectOne(queryWrapper);
    }

    @Override
    public void sendLoginCode(String phoneNumber) throws Exception {
        //判断一分钟内是否发送过验证码
        if (redisUtil.exists(RedisKeyUtil.ADMIN_LOGIN_CODE_SENT(phoneNumber))){
            throw new Exception("验证码发送频繁");
        }
        //判断一小时内的发送次数
        if(redisUtil.exists(RedisKeyUtil.SENT_ADMIN_LOGIN_CODE_NUMBER(phoneNumber))){
            int number = Integer.parseInt(redisUtil.get(RedisKeyUtil.SENT_ADMIN_LOGIN_CODE_NUMBER(phoneNumber)));
            if (number>=5){
                throw new Exception("验证码发送次数过多");
            }

        }
        //验证手机号是否被注册
        QueryWrapper<AdminInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("admin_phone",phoneNumber).ne("admin_state",2);
        List<AdminInfo> adminInfos = adminInfoMapper.selectList(wrapper);
        if (adminInfos.isEmpty()){
            throw new Exception("用户手机号未注册或状态异常");
        }
        if (adminInfos.get(0).getAdminState()==1)throw new Exception("用户状态异常");
        //将手机号码保存到队列中
        rabbitTemplate.convertAndSend("admin_login_phone_queue",phoneNumber);
    }

    @Override
    public AdminInfo adminCodeLogin(AdminCodeLoginParam param) throws Exception {
        //用户在发送验证码时的验证码
        String code = redisUtil.get(RedisKeyUtil.ADMIN_LOGIN_CODE_KEY(param.getUserPhone()));

        System.out.println("前端传过来的验证码"+param.getCode());
        System.out.println("发送验证码时存在redis中的验证码"+code);

        //输入的验证码与发送的手机验证码不相同
        if (!param.getCode().equals(code)){
            throw new Exception("验证码不正确");
        }
        //查询用户
        QueryWrapper<AdminInfo> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("admin_phone",param.getUserPhone())
                .eq("admin_state",0);
        List<AdminInfo> adminInfos = adminInfoMapper.selectList(queryWrapper);
        //未查询到用户
        if (adminInfos.isEmpty()){//为空表示手机号未注册或账号失效
            throw new Exception("手机号未注册过或账号已失效");
        }
        AdminInfo adminInfo = adminInfos.get(0);
        //写入登录日志
        Log log = new Log();
        log.setAccountId(adminInfo.getAdminId());
        log.setLogTime(LocalDateTime.now());
        log.setUserType(adminInfo.getRoleId());
        log.setLoginHost(InetAddress.getLocalHost().getHostAddress());
        log.setControls("手机号登录");
        logMapper.insert(log);

        return adminInfo;
    }

    @Override
    public Page<AdminInfo> findByStationId(@RequestBody FindSuitableRiderDTO dto) {
        Page<AdminInfo> page = new Page<>(dto.getPageNum(),dto.getPageSize());
        QueryWrapper<AdminInfo> wrapper = new QueryWrapper<>();
        List<Integer> list = dto.getAdminId();
        wrapper.eq("station_id",dto.getStationId()).eq("adminState",0).eq("role_id",0);
        // 如果 adminId 列表不为空，添加排除条件
        if (list != null && !list.isEmpty()) {
            wrapper.notIn("admin_id", list);
        }
        Page<AdminInfo> infoPage = adminInfoMapper.selectPage(page, wrapper);
        return infoPage;
    }

    @Override
    public List<AdminInfo> selectAdmin() {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        //状态正常/没有站点信息/角色为站长
        queryWrapper.eq("admin_state",0).eq("station_id",0).eq("role_id",3);
        List<AdminInfo> adminInfos = adminInfoMapper.selectList(queryWrapper);
        return adminInfos;
    }

    @Override
    public AdminInfo selectAdminByAdminName(String adminName) {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("admin_name",adminName);
        AdminInfo adminInfo = adminInfoMapper.selectOne(queryWrapper);
        return adminInfo;
    }

    @Override
    public List<AdminInfo> findByStation(Integer stationId) {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("station_id",stationId).eq("admin_state",0).eq("role_id",1);
        List<AdminInfo> adminInfos = adminInfoMapper.selectList(queryWrapper);
        return adminInfos;
    }

    @Override
    public List<AdminInfo> findAdmin(FindAdminDTO dtos) {
        QueryWrapper<AdminInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("station_id",dtos.getStationId()).eq("admin_state",0).eq("role_id",1);
        if (!dtos.getList().isEmpty() || dtos.getList().size()!=0){
            queryWrapper.notIn("admin_id", dtos.getList());
        }
        List<AdminInfo> infos = adminInfoMapper.selectList(queryWrapper);
        return infos;
    }
}
